﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO;
using System.Collections;
using System.Text.RegularExpressions;
using System.Xml;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Diagnostics;
using System.Threading;
using PIAE.Tools;
using System.Globalization;

namespace PIAE
{
    public partial class MainForm : Form
    {

        SizePattern[] sizes;
        public static String Separator = "---------------------------------";

        Hashtable nameToFile = new Hashtable();
        FolderBrowserDialog brw = new FolderBrowserDialog();

        public static String version = "1.1";
        private String dangerouschars = "["+ Regex.Escape ( new String( System.IO.Path.GetInvalidFileNameChars() ) )+"]";
        ArrayList filePairs = new ArrayList();

        int fileNumber = 0;
        int copiedFiles = 0;

        private CultureInfo langEnglishCulture = new CultureInfo("en-US");
        private CultureInfo langFrenchCulture = new CultureInfo("fr-FR");
        private CultureInfo langGermanCulture = new CultureInfo("de-DE");
        private CultureInfo langItalianCulture = new CultureInfo("it-IT");
        private CultureInfo langPolishCulture = new CultureInfo("pl-PL");

        public MainForm()
        {
            //MessageBox.Show("Start");
            //MessageBox.Show("Check if Picasa is running");
            if (Program.initLang.Length > 0)
            {
                MyResourceManager.Culture = Program.initLang;
                
            }
            if (true == Program.forceError)
            {
                ErrorBox.showError(String.Format("This is simulated error to test language versions of error box"));
                Environment.Exit(0);
            }

            CheckPicasaRunning();

            //MessageBox.Show("Initialize main window");
            InitializeComponent();
            updateUI();
            //MessageBox.Show("Get defauls save path");
            initData();
            //MessageBox.Show("Initialize background worker");
            InitializeBackgoundWorker();
            //MessageBox.Show("Initialize sizes list");
            InitSizes();
            InitLang();
            loadAlbums();
            updatePattern();
            comboResize.SelectedIndex = 0;
            showProgressPanel(false);
        }

        private void InitLang()
        {
            langComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
            langComboBox.ImageList = countryImageList;
            langComboBox.Items.Add(new ComboBoxExItem("English", 0));
            langComboBox.Items.Add(new ComboBoxExItem("French", 1));
            langComboBox.Items.Add(new ComboBoxExItem("Deutsch", 2));
            langComboBox.Items.Add(new ComboBoxExItem("Italiano", 3));
            langComboBox.Items.Add(new ComboBoxExItem("Polski", 4));

            if (0 == Program.initLang.Length)
            {
                if (Thread.CurrentThread.CurrentUICulture.Name.StartsWith("pl") )
                {
                    langComboBox.SelectedIndex = 4;
                }
                else if (Thread.CurrentThread.CurrentUICulture.Name.StartsWith("it") )
                {
                    langComboBox.SelectedIndex = 3;
                }
                else if (Thread.CurrentThread.CurrentUICulture.Name.StartsWith("de") )
                {
                    langComboBox.SelectedIndex = 2;
                }
                else if (Thread.CurrentThread.CurrentUICulture.Name.StartsWith("fr") )
                {
                    langComboBox.SelectedIndex = 1;
                }
                else if (Program.initLang.Equals("en"))
                {
                    langComboBox.SelectedIndex = 0;
                }
                else // default english
                {
                    langComboBox.SelectedIndex = 0;
                }
            }

        }

        private void CheckPicasaRunning()
        {
            Process[] p2 = Process.GetProcessesByName("Picasa2");
            Process[] p3 = Process.GetProcessesByName("Picasa3");
            if (p2.Length > 0 || p3.Length > 0 )
            {
                if (DialogResult.Yes != MessageBox.Show(
                    MyResourceManager.GetString("IfPicasaIsCurrentlyRunning"),
                    MyResourceManager.GetString("Continue"),
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Exclamation
                    ))
                {
                    Environment.Exit(0);
                }
            }
        }

        void InitSizes()
        {
            sizes = new SizePattern[]
            {
                new SizePattern(0,0,MyResourceManager.GetString("OriginalSize")),
                new SizePattern(0, 0, Separator),
                new SizePattern(1366, 768, "HD-Ready TV  (1366×768)"),
                new SizePattern(1920, 1080, "Full-HD TV (1920×1080)"),
                new SizePattern(0, 0, Separator),
                new SizePattern(800, 600, "800×600 (SVGA)"),
                new SizePattern(1024, 768, "1024×768 (XGA)"),
                new SizePattern(1280, 800, "1280×800 (WXGA)"),
                new SizePattern(1280, 960, "1280×960 (SGA)"),
                new SizePattern(1280, 1024, "1280×1024 (SXGA)"),
                new SizePattern(1600, 1200, "1600×1200 (UXGA)"),
                new SizePattern(0, 0, Separator),
                new SizePattern(0,0,MyResourceManager.GetString("CustomSize"))
            };
            
            foreach (SizePattern s in sizes)
            {
                comboResize.Items.Add(s.nazwa);
            }
        }

        private void initData()
        {
            brw.SelectedPath = Environment.GetFolderPath(
                Environment.SpecialFolder.MyComputer);
            this.Text += " v" + version;
        }

        private void InitializeBackgoundWorker()
        {
            bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
      
            bgWorker.RunWorkerCompleted +=
                new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);

            bgWorker.ProgressChanged +=
                new ProgressChangedEventHandler(bgWorker_ProgressChanged);
            
        }

        private void bgWorker_ProgressChanged(object sender,
            ProgressChangedEventArgs e)
        {
            this.progressBar.Value = e.ProgressPercentage;
        }


        private void loadAlbums()
        {
            //MessageBox.Show("Get albums folder");

            String albumsPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) +
                "\\Google\\Picasa2Albums";

            //MessageBox.Show("Check if albums folder exists");
            if (false == Directory.Exists(albumsPath))
            {
                ErrorBox.showError(String.Format(MyResourceManager.GetString("DirectoryWasNotFoundItLooks"), albumsPath));
                Environment.Exit(0);
            }

            //MessageBox.Show("Get folder files list");
            String[] albumFiles = Directory.GetFiles(albumsPath, "*.pal", SearchOption.AllDirectories);

            if (albumFiles.Length == 0 || true == Program.forceNoAlbum)
            {
                new ErrorNoAlbums(albumsPath).ShowDialog();
                Environment.Exit(0);
            }

            ArrayList albumList = new ArrayList();

            foreach (String albumFile in albumFiles)
            {
                if (albumFile.ToLower().Contains("\\backup\\"))
                {
                    continue;
                }
                //MessageBox.Show("Try to parse "+albumFile);

                XmlTextReader reader = new XmlTextReader(albumFile);
                int j = 0;
                String albumName = "";
                DateTime albumDate = DateTime.Now;
                
                while (reader.Read())
                {
  
                    if (reader.NodeType.Equals(XmlNodeType.Element))
                    {

                        if (reader.Name.Equals("property") &&
                            reader.GetAttribute("name").Equals("name") 
                            )
                        {
                            if (0 == numberAlbumFile(albumFile))
                            {
                                ErrorBox.showError(String.Format(MyResourceManager.GetString("File0LooksLikePicasaAlbum"), albumFile));
                                Environment.Exit(0);
                            }
                                                                                    
                           albumName = reader.GetAttribute("value");
                           j++;
                        }

                        if (reader.Name.Equals("property") &&
                            reader.GetAttribute("name").Equals("date") 
                            )
                        {
                            String rawdate = reader.GetAttribute("value");
                            Double formatteddate = Convert.ToDouble(rawdate, CultureInfo.InvariantCulture);
                            albumDate = DateTime.FromOADate(formatteddate);
                            j++;
                        }

                        if (j == 2) // if both name and date have been found
                        {
                            albumName = albumDate.ToString("yyyy/MM/dd") + "   " + albumName;
                            while (nameToFile.Contains(albumName))
                            {
                                albumName += "*";
                            }
                            nameToFile.Add(
                                albumName,
                                albumFile);

                            albumList.Add(albumName);
                            break;
                            
                        }
                    }
                }
            }
            albumList.Sort();
            albumList.Reverse();
            foreach (string str in albumList)
            {
                albumyCombo.Items.Add(str);
            }
            albumyCombo.SelectedIndex = 0;
        }


        private int numberAlbumFile(String filename)
        {
            XmlTextReader reader = new XmlTextReader(filename);
            int licznik = 0;

            while (reader.Read())
            {
                if (reader.NodeType.Equals(XmlNodeType.Element))
                {
                    if (reader.Name.Equals("filename") )
                    {
                        licznik++;
                    }
                }
            }
            return licznik;
        }

        private Boolean isFilenameResizableImage(String s)
        {
            String extension = s.Substring(s.LastIndexOf(".") + 1).ToLower();
            return (
                   true == extension.Equals("jpg", StringComparison.InvariantCultureIgnoreCase)
                || true == extension.Equals("jpeg", StringComparison.InvariantCultureIgnoreCase)
                || true == extension.Equals("png", StringComparison.InvariantCultureIgnoreCase)
                || true == extension.Equals("gif", StringComparison.InvariantCultureIgnoreCase)
                || true == extension.Equals("bmp", StringComparison.InvariantCultureIgnoreCase)
                || true == extension.Equals("tif", StringComparison.InvariantCultureIgnoreCase)
                || true == extension.Equals("tiff", StringComparison.InvariantCultureIgnoreCase)
            );
        }

        private void copyBtn_Click(object sender, EventArgs e)
        {

            filePairs.Clear();

            if (comboResize.SelectedIndex == comboResize.Items.Count - 1)
            {
                sizes[sizes.Length - 1].x = (int)customWidth.Value;
                sizes[sizes.Length - 1].y = (int)customHeight.Value;
            }

            if (dirTextBox.Text.Length == 0)
            {
                MessageBox.Show(MyResourceManager.GetString("ChooseDestinationDirectoryFirst"), MyResourceManager.GetString("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            String albumFile = nameToFile [albumyCombo.SelectedItem.ToString()].ToString();

            fileNumber = numberAlbumFile(albumFile);
            int digitsNo = (int)Math.Ceiling( Math.Log10(fileNumber) );
            int counter = (int)numericFirst.Value;
            long bytesToCopy = 0;

            
            if ( true == radioButtonCustom.Checked )
            {
                int digitsInPatt = numHashPattern(pattern.Text);

                if (0 == digitsInPatt)
                {
                    MessageBox.Show(MyResourceManager.GetString("ThereAreNoNumberWildcards"), MyResourceManager.GetString("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                if (-1 == digitsInPatt)
                {
                    MessageBox.Show(MyResourceManager.GetString("ThereAreMultipleNumberWildcards"), MyResourceManager.GetString("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                if (digitsNo > digitsInPatt)
                {
                    MessageBox.Show(String.Format(MyResourceManager.GetString("ThereMustBeAtLeastDigits"), digitsNo), MyResourceManager.GetString("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                if (true == Regex.IsMatch(pattern.Text, dangerouschars))
                {
                    MessageBox.Show(MyResourceManager.GetString("ForbiddenCharactersInPattern"), MyResourceManager.GetString("Information"), MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                digitsNo = digitsInPatt;
            }
            
            XmlTextReader reader = new XmlTextReader(albumFile);

            Boolean acceptedNonresizableElements = false;

            while (reader.Read())
            {
                if (reader.NodeType.Equals(XmlNodeType.Element) && reader.Name.Equals("filename") )
                {
                    String sourceFile = reader.ReadElementContentAsString();
                    sourceFile = Regex.Replace(sourceFile, "^\\[(.)\\]", "$1:");
                    sourceFile = sourceFile.Replace(
                        "$Desktop",
                        Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
                    sourceFile = sourceFile.Replace(
                        "$My Computer",
                        Environment.GetFolderPath(Environment.SpecialFolder.MyComputer));
                    sourceFile = sourceFile.Replace(
                        "$My Pictures",
                        Environment.GetFolderPath(Environment.SpecialFolder.MyPictures));
                    sourceFile = sourceFile.Replace(
                        "$Program files",
                        Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles));
                    sourceFile = sourceFile.Replace(
                        "$My Documents",
                        Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
                    sourceFile = sourceFile.Replace(
                        "$My Music",
                        Environment.GetFolderPath(Environment.SpecialFolder.MyMusic));
                    sourceFile = sourceFile.Replace(
                        "$Application Data",
                        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
                    sourceFile = sourceFile.Replace(
                        "$Common Application Data",
                        Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
                    if (false == File.Exists(sourceFile))
                    {
                        MessageBox.Show(
                            String.Format(
                            MyResourceManager.GetString("AlbumContainsFileWhichCannot"),sourceFile),
                            MyResourceManager.GetString("Error"),
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Stop);
                        return;
                    }
                    FileInfo info = new FileInfo(sourceFile);
                    bytesToCopy += info.Length;

                    String destinationFile = "";
                    String destWithoutPath = null;

                    String err = null;

                    destWithoutPath = getNameFromPattern(
                        pattern.Text,
                        info.Name,
                        counter,
                        ref err)+info.Extension;
                    
                    if (null != err)
                    {
                        MessageBox.Show(
                            err,
                            MyResourceManager.GetString("Alert"),
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Stop);
                        return;
                    }
                    
                    destinationFile = String.Format(
                        "{0}" + Path.DirectorySeparatorChar + "{1}",
                        dirTextBox.Text,
                        destWithoutPath
                        );

                    if (File.Exists(destinationFile))
                    {
                        MessageBox.Show(
                            String.Format(
                            MyResourceManager.GetString("DestinationFileAlreadyExists"),destinationFile),
                            MyResourceManager.GetString("Error"),
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Stop);
                        return;
                    }

                    if (comboResize.SelectedIndex != 0 && false == acceptedNonresizableElements)
                    {
                        if (false == isFilenameResizableImage(destinationFile))
                        {
                            String extension = destinationFile.Substring(destinationFile.LastIndexOf(".") + 1);
                            if (DialogResult.Cancel == MessageBox.Show(
                                String.Format(
                                MyResourceManager.GetString("PIAEDoesNotSupportResize"),extension.ToUpper()),
                                MyResourceManager.GetString("CannotResizeSomeFiles"),
                                MessageBoxButtons.OKCancel,
                                MessageBoxIcon.Exclamation)
                                )
                            {
                                return;
                            }
                            else
                            {
                                acceptedNonresizableElements = true;
                            };
                        }

                    }

                    filePairs.Add( new FilePair( sourceFile, destinationFile));
                    counter++;
                }
            }

            if (GetDiskFreeSpace(dirTextBox.Text) < bytesToCopy )
            {
                String msg = String.Format(MyResourceManager.GetString("DestinationDiskHasMBFree"),
                    GetDiskFreeSpace(dirTextBox.Text)/1024.0/1024.0,
                    bytesToCopy/1024.0/1024.0);
                MessageBox.Show(
                    msg,
                    MyResourceManager.GetString("Error"),
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                return;
            }

            int destx = -1;
            int desty = -1;

            if (comboResize.SelectedIndex != 0)
            {
                destx = sizes[comboResize.SelectedIndex].x;
                desty = sizes[comboResize.SelectedIndex].y;
            }
            String msg2 = "";

            if (destx > 0)
            {
                msg2 = String.Format(
                    MyResourceManager.GetString("FilesWillBeResizedToFitIn"),
                    filePairs.Count,
                    dirTextBox.Text,
                    destx, desty);
            }
            else
            {
                msg2 = String.Format(
                    MyResourceManager.GetString("MBInFilesWillBeCopied"),
                    bytesToCopy / 1024.0 / 1024.0,
                    filePairs.Count,
                    dirTextBox.Text);
            }

            if (DialogResult.Yes == MessageBox.Show(
                msg2,
                MyResourceManager.GetString("Continue"),
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question
                ))
            {

                copyBtn.Enabled = false;
                panelMain.Enabled = false;
                showProgressPanel(true);
                bgWorker.RunWorkerAsync(new int[]{ destx, desty });
            }
        }

        private void showProgressPanel(bool show)
        {
            progressPanel.Visible = show;
            aboutExitPanel.Visible = !show;
            if (show)
            {
                progressPanel.BringToFront();
            }
            else
            {
                aboutExitPanel.BringToFront();
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void dirBtn_Click(object sender, EventArgs e)
        {
            brw.ShowNewFolderButton = true;
            if (DialogResult.OK == brw.ShowDialog())
            {
                try
                {
                    dirTextBox.Text = brw.SelectedPath;
                }
                catch (NotSupportedException)
                {
                    dirTextBox.Text = "";
                }
                
            }
        }


        private void albumyCombo_SelectedValueChanged(object sender, EventArgs e)
        {
            albumyComboChanged();
        }

        private void albumyComboChanged()
        {
            if (albumyCombo.SelectedItem != null)
            {
                fileNumber = numberAlbumFile(nameToFile[albumyCombo.SelectedItem.ToString()].ToString());
                counterLabel.Text = String.Format(MyResourceManager.GetString("ThisAlbumContainsPictures"), fileNumber);
                updateAutoPattern();
            }
        }

        private void Exit_Click(object sender, EventArgs e)
        {
            Dispose();
        }


    public struct DiskFreeSpace
    {
        public long FreeBytesAvailable;
        public long TotalBytes;
        public long TotalFreeBytes;
    }

    public static long GetDiskFreeSpace(string directoryName)
    {
        DiskFreeSpace result = new DiskFreeSpace();
        if( false == GetDiskFreeSpaceEx(directoryName, ref result.FreeBytesAvailable,
            ref result.TotalBytes, ref result.TotalFreeBytes))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(), MyResourceManager.GetString("ErrorRetrievingFreeDiskSpace"));
        }
        return result.FreeBytesAvailable;
    }

    [DllImport("kernel32.dll")]
    private static extern bool GetDiskFreeSpaceEx(string directoryName,
        ref long freeBytesAvailable,
        ref long totalBytes,
        ref long totalFreeBytes);

    private void aboutBtn_Click(object sender, EventArgs e)
    {
        new AboutBox().ShowDialog();
    }

    /* -1 = multiple hash, 0 = no hash, 1+ = number of chars */
    private int numHashPattern(String str)
    {
        if (str.IndexOf('#') < 0)
        {
            return 0;
        }

        bool started = false;
        bool finished = false;
        int counter = 0;

        for (int i = 0; i < str.Length; i++)
        {
            if (str[i] == '#')
            {
                if (finished == true)
                {
                    return -1;
                }
                counter++;
                started = true;
            }
            else
            {
                if (started == true)
                {
                    finished = true;
                }
            }
        }
        return counter;
    }

    private String getMultiple(char c, int howMany)
    {
        String ret = "";
        for (int i = 0; i < howMany; i++)
        {
            ret += c;
        }
        return ret;
    }

    private String getNameFromPattern(String pattern, String original, int number, ref String error)
    {
        String dest = pattern;

        if (dest.IndexOf("%") >= 0 )
        {
            if (original.IndexOf(".") > 0)
            {
                dest = dest.Replace("%", original.Substring(0, original.LastIndexOf(".")));
            }
            else
            {
                dest = dest.Replace("%", original);
            }

        }
        int charno = numHashPattern(dest);

        if (0 == charno)
        {
            error = MyResourceManager.GetString("SHORTSMissing");
            return null;
        }

        if (-1 == charno)
        {
            error = MyResourceManager.GetString("SHORTTwoBlocksOfS");
            return null;
        }

        int digitsNo = (int)Math.Ceiling(Math.Log10(number));
        if (digitsNo > charno)
        {
            error = String.Format( MyResourceManager.GetString("SHORTThereMustBeAtLeastDigits"), digitsNo);
            return null;
        }

        if ( true == Regex.IsMatch(pattern, dangerouschars))
        {
            error = MyResourceManager.GetString("SHORTIllegalChars");
            return null;
        }

        if (charno < 1)
        {
            error = MyResourceManager.GetString("SHORTInvalidPattern");
            return null;
        }
        else
        {
            dest = dest.Replace(
                getMultiple('#', charno),
                getNumberAsString(number, charno)
            );
        }
        return dest;
    }

    private String getNumberAsString(int number, int length)
    {
        String ret = number.ToString();
        while (ret.Length < length)
        {
            ret = "0" + ret;
        }
        return ret;

    }

    private void updatePattern()
    {
        //MessageBox.Show("Initialize replace name pattern");

        String pat = pattern.Text.Replace(".jpg", "");
        String err = "";
        String dest = getNameFromPattern(pat, "party", fileNumber, ref err);
        if (null == dest)
        {
            sampleDestination.BackColor = Color.LightPink;
            sampleDestination.Text = err;
        }
        else
        {
            sampleDestination.BackColor = System.Drawing.SystemColors.Control;
            sampleDestination.Text = dest + ".jpg";
        }
    }

    private void updateAutoPattern()
    {
        String str = "#";

        int digitsNo = (int)Math.Ceiling(Math.Log10(fileNumber+ (int)numericFirst.Value ));
        for (int i = 1; i < digitsNo; i++)
        {
            str += "#";
        }

        if (true == radioButtonNumbers.Checked)
        {
            pattern.Text = str;
        }

        if (true == radioButtonWithOrig.Checked)
        {
            pattern.Text = str+"-%";
        }




    }

    private void updatePatternWidgets()
    {
        if (true == radioButtonCustom.Checked)
        {
            pattern.Enabled = true;
            labelH3.Enabled = true;
            labelH4.Enabled = true;
        }
        else
        {
            pattern.Enabled = false;
            labelH3.Enabled = false;
            labelH4.Enabled = false;
        }

        updateAutoPattern();
    }

    private void pattern_TextChanged(object sender, EventArgs e)
    {
        updatePattern();
    }

    private void radioButtonNumbers_CheckedChanged(object sender, EventArgs e)
    {
        updatePatternWidgets();
    }

    private void radioButtonWithOrig_CheckedChanged(object sender, EventArgs e)
    {
        updatePatternWidgets();
    }

    private void radioButtonCustom_CheckedChanged(object sender, EventArgs e)
    {
        updatePatternWidgets();
    }


    class SizePattern 
    {
        public SizePattern(int initx, int inity, String initnazwa)
        {
            x = initx;
            y = inity;
            nazwa = initnazwa;
        }
        public int x;
        public int y;
        public String nazwa;
    }

    private void comboResize_SelectedIndexChanged(object sender, EventArgs e)
    {
        labelRatioWarning.Visible = (0 != comboResize.SelectedIndex);
        if (null != comboResize.SelectedItem && comboResize.SelectedItem.ToString().Equals(Separator))
        {
            comboResize.SelectedIndex = comboResize.SelectedIndex - 1;
        }

        if (comboResize.SelectedIndex == comboResize.Items.Count - 1)
        {
            customHeight.Visible = true;
            customHeightLbl.Visible = true;
            customWidth.Visible = true;
            customWidthLbl.Visible = true;
        }
        else
        {
            customHeight.Visible = false;
            customHeightLbl.Visible = false;
            customWidth.Visible = false;
            customWidthLbl.Visible = false;
        }

    }

    private void numericFirst_ValueChanged(object sender, EventArgs e)
    {
        updateAutoPattern();
    }

    private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        copiedFiles = 0;

        int destx = ((int[])e.Argument)[0];
        int desty = ((int[])e.Argument)[1];

        String msg = null;

        filePairs.Sort();
        foreach (FilePair source in filePairs)
        {
            if (true == bgWorker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }

            String destination = source.getDest();
            bgWorker.ReportProgress( (int)(100.0*(copiedFiles)/filePairs.Count ));
            
            //for debug purposes
            // Thread.Sleep(2000);

            try
            {
//              System.IO.File.Move(
                System.IO.File.Copy(source.getSource(), destination);
//                System.IO.File.SetCreationTime(destination, System.IO.File.GetCreationTime(source.getSource()));
//                System.IO.File.SetLastAccessTime(destination, System.IO.File.GetLastAccessTime(source.getSource()));
//                System.IO.File.SetLastWriteTime(destination, System.IO.File.GetLastWriteTime(source.getSource()));
            }
            catch (System.UnauthorizedAccessException)
            {
                msg = MyResourceManager.GetString("UnauthorizedAccess");
            }
            catch (System.IO.PathTooLongException)
            {
                msg = MyResourceManager.GetString("PathIsTooLong");
            }
            catch (System.IO.IOException)
            {
                if (File.Exists(destination))
                {
                    msg = MyResourceManager.GetString("FileAlreadyExists");
                }
                else
                {
                    msg = MyResourceManager.GetString("IOException");
                }
                
            }
            catch (System.NotSupportedException)
            {
                msg = MyResourceManager.GetString("OperationIsNotSupported");
            }

            if (msg != null)
            {
                e.Result = new String[] {msg, source.getSource(), destination};
                return;
            }

            copiedFiles++;

            if (destx > 0 && isFilenameResizableImage(destination))
            {
                using (Image src = Image.FromFile(destination))
                {
                    ImageFormat origFormat = src.RawFormat;
                    double ratio = Math.Min(destx * 1.0d / src.Width, desty * 1.0d / src.Height);
                    if (ratio < 1.0f)
                    {
                        int newwidth = (int)(ratio * src.Width);
                        int newheight = (int)(ratio * src.Height);
                        using (Bitmap dst = new Bitmap(newwidth, newheight))
                        {
                            using (Graphics g = Graphics.FromImage(dst))
                            {
                                g.SmoothingMode = SmoothingMode.AntiAlias;
                                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                                g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;

                                g.DrawImage(src, 0, 0, newwidth, newheight);
                                g.Dispose();
                            }

                            // Copy original Bitmap's EXIF tags to new bitmap.
                            foreach (PropertyItem propertyItem in src.PropertyItems)
                            {
                                dst.SetPropertyItem(propertyItem);
                            }

                            src.Dispose();

                            dst.Save(destination, origFormat);
                        }
                    }
                }
                
            }
        }
        if (msg != null)
        {
            e.Result = msg;
        }
    }

    private void bgWorker_RunWorkerCompleted(
        object sender, RunWorkerCompletedEventArgs e)
    {
        copyBtn.Enabled = true;
        panelMain.Enabled = true;
        progressBar.Value = 0;
        showProgressPanel(false);

        // weird logic below, but if cancelled, e.Result is unavailable
        if (true == e.Cancelled)
        {
            String toShow = String.Format(MyResourceManager.GetString("OperationCancelledAfter0CopiedFiles"), copiedFiles);
            MessageBox.Show(toShow, MyResourceManager.GetString("Cancelled"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }
        else
        {

            if (e.Result == null)
            {
                String toShow = String.Format(MyResourceManager.GetString("FilesWereSuccessfullyCopied"), copiedFiles);
                MessageBox.Show(toShow, MyResourceManager.GetString("Done"), MessageBoxButtons.OK, MessageBoxIcon.Information);

            }
            else
            {
                String toShow = String.Format(
                    MyResourceManager.GetString("FollowingErrorOccured"),
                    ((String[])e.Result)[0],
                    ((String[])e.Result)[1],
                    ((String[])e.Result)[2]
                    );
                MessageBox.Show(toShow, MyResourceManager.GetString("Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }

    private void cancelCopying()
    {
        bgWorker.CancelAsync();

    }

    private void cancelBtn_Click(object sender, EventArgs e)
    {
        cancelCopying();
    }

    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (bgWorker.IsBusy)
        {
            cancelCopying();
            e.Cancel = true;
        }
    }

    private void updateUI()
    {
        //this.copyBtn.Text = global::PIAE.Properties.LangResources.ExportPictureFiles;
        this.copyBtn.Text = MyResourceManager.GetString("ExportPictureFiles");

        this.label1.Text = MyResourceManager.GetString("ChooseAlbumToExportFrom");
        this.label3.Text = MyResourceManager.GetString("ChooseDestinationDirectory");
        this.label4.Text = MyResourceManager.GetString("ChooseNamingConvention");
        this.radioButtonNumbers.Text = MyResourceManager.GetString("NumberOnly");
        this.radioButtonWithOrig.Text = MyResourceManager.GetString("NumberWithOriginalName");
        this.labelH1.Text = MyResourceManager.GetString("FirstPictureNumber");
        this.labelH3.Text = MyResourceManager.GetString("FilenamePattern");
        this.labelH4.Text = MyResourceManager.GetString("DigitOriginalName");
        this.labelH5.Text = MyResourceManager.GetString("ExampleSource");
        this.labelH6.Text = MyResourceManager.GetString("ExampleDestination");
        this.radioButtonCustom.Text = MyResourceManager.GetString("CustomNamePattern");
        this.label2.Text = MyResourceManager.GetString("ChooseResizeSettings");
        this.labelRatioWarning.Text = MyResourceManager.GetString("NoteAspectRatioRemainsUnchangedSmallerPicturesWonTBeUpscaled");
        this.customWidthLbl.Text = MyResourceManager.GetString("Width");
        this.customHeightLbl.Text = MyResourceManager.GetString("Height");
        this.cancelBtn.Text = MyResourceManager.GetString("Cancel");
        this.Exit.Text = MyResourceManager.GetString("Exit");
        this.aboutBtn.Text = MyResourceManager.GetString("About");
        albumyComboChanged();

        if (comboResize.Items.Count > 0)
        {
            int pos = comboResize.SelectedIndex;
            comboResize.Items.RemoveAt(0);
            comboResize.Items.Insert(0, MyResourceManager.GetString("OriginalSize"));
            comboResize.Items.RemoveAt(comboResize.Items.Count - 1);
            comboResize.Items.Add(MyResourceManager.GetString("CustomSize"));
            comboResize.SelectedIndex = pos;
        }
    }

    private void langComboBox_SelectedIndexChanged(object sender, EventArgs e)
    {

        switch (langComboBox.SelectedIndex)
        {
            case 0: Thread.CurrentThread.CurrentUICulture = langEnglishCulture; MyResourceManager.Culture = "en-EN"; break;
            case 1: Thread.CurrentThread.CurrentUICulture = langFrenchCulture; MyResourceManager.Culture = "fr-FR"; break;
            case 2: Thread.CurrentThread.CurrentUICulture = langGermanCulture; MyResourceManager.Culture = "de-DE"; break;
            case 3: Thread.CurrentThread.CurrentUICulture = langItalianCulture; MyResourceManager.Culture = "it-IT"; break;
            case 4: Thread.CurrentThread.CurrentUICulture = langPolishCulture; MyResourceManager.Culture = "pl-PL"; break;

        }

        updateUI();
    }


  }

    class FilePair : IComparable
    {
        String source;
        String destination;

        public FilePair(String s, String d)
        {
            source = s;
            destination = d;
        }

        public String getSource()
        {
            return source;
        }

        public String getDest()
        {
            return destination;
        }


        #region IComparable Members

        public int CompareTo(object obj)
        {
            if (obj is FilePair)
            {
                return getDest().CompareTo(((FilePair)obj).getDest());
            }
            throw new NotImplementedException();
        }

        #endregion
    }

}


